package com.app.module.camera.core.observer

import android.content.Context
import android.opengl.EGLSurface
import android.opengl.GLES20
import android.view.Surface
import com.app.module.camera.core.FrameBean
import com.app.module.camera.renderer.base.DefaultRenderer
import com.app.module.camera.utils.MatrixUtils
import com.app.module.camera.utils.MatrixUtils.Companion.TYPE_CENTERCROP
import java.util.*

open class FramePreviewer(protected val mContext: Context) : Observer {

    private var mShowSurface: EGLSurface? = null
    private var mFilter: DefaultRenderer = DefaultRenderer()

    @Volatile
    private var mSurface: Surface? = null

    @Volatile
    private var isShow = false

    @Volatile
    private var isRecycle = false

    private var mWidth: Int = 0
    private var mHeight: Int = 0

    private var mMatrixType = TYPE_CENTERCROP

    open fun setOutputSize(width: Int, height: Int) {
        mWidth = width
        mHeight = height
    }

    fun getWidth(): Int = this.mWidth

    fun getHeight(): Int = this.mHeight

    open fun setSurface(Surface: Surface) {
        mSurface = Surface
    }

    open fun recycle() {
        isRecycle = true
    }

    open fun open() {
        isShow = true
    }

    open fun close() {
        isShow = false
    }

    private fun frameChange(rb: FrameBean) {
        if (rb.endFlag && mShowSurface != null) {
            rb.egl.destroySurface(mShowSurface)
            mShowSurface = null
        } else if (isShow && mSurface != null && !isRecycle) {
            if (mShowSurface == null) {
                mShowSurface = rb.egl.createWindowSurface(mSurface!!)
                mFilter.create()
                mFilter.sizeChanged(rb.size.width, rb.size.height)
                MatrixUtils.getMatrix(mFilter.getVertexMatrix(), mMatrixType, rb.size.width, rb.size.height, mWidth, mHeight)
                MatrixUtils.flip(mFilter.getVertexMatrix(), false, true)
            }
            rb.egl.makeCurrent(mShowSurface)
            GLES20.glViewport(0, 0, mWidth, mHeight)
            mFilter.draw(rb.textureId)
            finishDraw(mShowSurface, rb)
            rb.egl.swapBuffers(mShowSurface)
        } else if (isRecycle) {
            isRecycle = false
            mShowSurface?.also {
                rb.egl.destroySurface(it)
            }
            mShowSurface = null
            isShow = false
        }
    }

    open fun finishDraw(surface: EGLSurface?, bean: FrameBean) {

    }

    override fun update(o: Observable?, arg: Any?) {
        if (arg is FrameBean) {
            frameChange(arg)
        }
    }

    fun isOpen() = isShow

}
